package com.zj.open.wechat.service;

import java.util.List;

import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zj.open.wechat.dto.event.Events;
import com.zj.open.wechat.dto.msg.Message;
import com.zj.open.wechat.dto.msg.Messages;

public abstract class MessageFactory {
    private static Logger logger = LoggerFactory.getLogger(MessageFactory.class);

    public static <T extends Message> T getMessage(Element root) {
        String msgType = root.element("MsgType").getStringValue();
        MessageFactory mf = "event".equals(msgType) ? new EventMessageFactory() : new NormalMessageFactory();
        return mf.createMessage(root);
    }

    abstract <T extends Message> T createMessage(Element root);

    static <T extends Message> T createMessageFromElements(List<Element> elements, Class<T> clazz) {
        try {
            T message = clazz.getDeclaredConstructor().newInstance();
            for (Element ele : elements) {
                try {
                    clazz.getMethod("set" + ele.getName(), String.class).invoke(message, ele.getStringValue());
                } catch (Exception e) {
                    logger.error("|MissingField|{}|{}", clazz.getSimpleName(), ele.getName());
                }
            }
            return message;
        } catch (Exception e) {
            logger.error("|WrongMessage|{}", clazz.getSimpleName());
        }
        return null;
    }

    @SuppressWarnings({ "unchecked" })
    static class EventMessageFactory extends MessageFactory {

        @Override
        <T extends Message> T createMessage(Element root) {
            String event = root.element("Event").getStringValue();
            Events events = Events.valueOf(event);
            if (events == null) {
                logger.error("|UnknownEvent|{}", event);
                return null;
            } else {
                return (T) createMessageFromElements((List<Element>) root.elements(), events.getEventClass());
            }

        }

    }

    static class NormalMessageFactory extends MessageFactory {
        @Override
        <T extends Message> T createMessage(Element root) {
            String msgType = root.element("MsgType").getStringValue();
            Messages messages = Messages.valueOf(msgType);
            if (messages == null) {
                logger.error("|UnknownMessage|{}", msgType);
                return null;
            } else {
                return (T) createMessageFromElements((List<Element>) root.elements(), messages.getMessageClass());
            }

        }
    }
}
